package com.jwds.digital.bios.business.service.service.belt.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltAnomalyInfo;
import com.jwds.digital.bios.business.core.infrastructure.vo.belt.BeltMonthlyAverageScoreVO;
import com.jwds.digital.bios.business.rpc.feign.BasicDeviceFeign;
import com.jwds.digital.bios.business.service.service.belt.IBeltAnomalyInfoService;
import com.jwds.digital.bios.business.service.service.belt.IBeltHealthDayService;
import com.jwds.digital.bios.business.core.infrastructure.dto.belt.BeltHealthDayReqDTO;
import com.jwds.digital.bios.business.core.infrastructure.vo.belt.BeltHealthDayRespVO;
import com.jwds.digital.bios.business.core.infrastructure.dto.belt.assembler.BeltHealthDayAssembler;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltHealthDay;
import com.jwds.digital.bios.business.core.infrastructure.mapper.belt.BeltHealthDayMapper;
import com.jwds.digital.bios.business.core.exceptions.RecordNotFoundException;
import com.jwds.digital.bios.business.service.service.belt.IBeltHealthScoreDayService;
import com.jwds.tdc.framework.application.lib.page.PageRequest;
import com.jwds.tdc.framework.application.lib.page.PageResponse;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 皮带健康数据汇总-天实现类
 * @author 林柏云
 * @date 2024-10-24
 */
@Slf4j
@Service
public class BeltHealthDayServiceImpl extends ServiceImpl<BeltHealthDayMapper, BeltHealthDay> implements IBeltHealthDayService {

  @Autowired
  private BeltHealthDayMapper baseMapper;

  @Resource
  private IBeltHealthScoreDayService beltHealthScoreDayService;

  @Resource
  private IBeltAnomalyInfoService beltAnomalyInfoService;

  @Resource
  private BasicDeviceFeign basicDeviceFeign;

  @Override
  public BeltHealthDayRespVO queryById(Long id) {
    if(id == null) {
      return null;
    }
    BeltHealthDay entity = baseMapper.selectById(id);
    return BeltHealthDayAssembler.entity2dto(entity);
  }

  @Override
  public PageResponse<BeltHealthDayRespVO> page(PageRequest<BeltHealthDayReqDTO> request) {
    BeltHealthDayReqDTO condition = request.getQueryCondition();
    Page<BeltHealthDayRespVO> page = new Page<>(request.getPageIndex(), request.getPageSize());
    IPage<BeltHealthDayRespVO> pageData = baseMapper.pageQuery(page, condition);
    return new PageResponse<>((Page<?>)pageData, pageData.getRecords());
  }

  @Override
  public List<BeltHealthDayRespVO> list(BeltHealthDayReqDTO reqDto) {
    return baseMapper.queryList(reqDto);
  }

  @Override
  public void add(BeltHealthDayReqDTO reqDto) {
    BeltHealthDay entity = BeltHealthDayAssembler.dto2entity(reqDto);
    baseMapper.insert(entity);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void batchAdd(List<BeltHealthDayReqDTO> dtoList) {
    dtoList.forEach(this::add);
  }

  @Override
  public void update(BeltHealthDayReqDTO reqDto) {
    BeltHealthDay oldEntity = baseMapper.selectById(reqDto.getId());
    if (oldEntity == null) {
      throw new RecordNotFoundException();
    }
    BeltHealthDay newEntity = BeltHealthDayAssembler.dto2entity(reqDto, oldEntity);
    baseMapper.updateById(newEntity);
  }

  @Override
  public void delete(Long id) {
    BeltHealthDay oldEntity = baseMapper.selectById(id);
    if (oldEntity == null) {
      throw new RecordNotFoundException();
    }
    baseMapper.deleteById(id);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void batchDelete(List<Long> ids) {
    for (Long id : ids) {
      delete(id);
    }
  }

  @Override
  public BeltHealthDayRespVO analyze(BeltHealthDayReqDTO reqDto) {
    Long id=reqDto.getId();
    String beltName=reqDto.getBeltName();
    // 从belt_health_score_day中查询健康、机械、五防分数
    Integer mechanicalScore=beltHealthScoreDayService.todayMechanicalScore(id);
    Integer fiveDefenseScore=beltHealthScoreDayService.todayFiveDefenseScore(id);
    Integer healthScore=beltHealthScoreDayService.todayHealthScore(id);
    // 从belt_anomaly_info中查询今日异常项
    List<BeltAnomalyInfo> anomalys=beltAnomalyInfoService.todayAnomalyItem(id);
    // 查询健康数据汇总
    LocalDateTime todayStart = LocalDate.now().atStartOfDay();
    LocalDateTime todayEnd = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59);
    // 查询这7天的数据健康数据汇总
    List<BeltHealthDay> beltHealthDayList= this.list(new LambdaQueryWrapper<BeltHealthDay>().eq(BeltHealthDay::getBeltName, beltName)
            .between(BeltHealthDay::getDate, todayStart.minusDays(7), todayStart).orderByAsc(BeltHealthDay::getDate));
    // 查询今日的数据
    BeltHealthDay beltHealthDay= baseMapper.analyze(beltName, todayStart,todayEnd);
    //如果beltHealthDay为空，查询昨天的数据
    if(beltHealthDay==null){
      beltHealthDay=baseMapper.analyze(beltName, todayStart.minusDays(1),todayEnd.minusDays(1));
      beltHealthDay= Optional.ofNullable(beltHealthDay).orElse(new BeltHealthDay());
    }

    // 计算出近12个月，每个月的平均机械分数、健康分数、五防分数
    List<BeltMonthlyAverageScoreVO> beltMonthlyAverageScoreVOList= beltHealthScoreDayService.monthlyAverageScore(id,todayStart);
    // 封装返回数据
    BeltHealthDayRespVO respVo = new BeltHealthDayRespVO();
    BeanUtils.copyProperties(beltHealthDay, respVo);
    respVo.setBeltMonthlyAverageScoreVOList(beltMonthlyAverageScoreVOList);
    respVo.setMechanicalScore(mechanicalScore);
    respVo.setFiveDefenseScore(fiveDefenseScore);
    respVo.setHealthScore(healthScore);
    respVo.setAnomalys(anomalys);
    respVo.setBeltHealthDayList(beltHealthDayList);
    respVo.setDeviceMark("直接启动/通用");
    respVo.setDeviceModel(basicDeviceFeign.queryById(id).getData().getDeviceName());
    respVo.setDeviceName("皮带机/通用");
    respVo.setAverageScore((mechanicalScore+fiveDefenseScore+healthScore)/3.0);
    return respVo;
  }


}